dd.animate({
    func:function()
    {
        
    },
    dd:{
        toRGBA:function(c)
        {
            if(c === "" || c === "transparent")
            {
                return {r:0, g:0, b:0, a:0};
            }
            else if(/#/.test(c))
            {
                if(c.length == 7)
                {
                    c = c.substring(1, 7);
                }
                var rgb = parseInt(c, 16); 
                return {
                    r:(rgb >> 16) & 0xFF,
                    g:(rgb >> 8) & 0xFF, 
                    b:rgb & 0xFF,
                    a:1
                };
            }
            else
            {
                var m = c.match(/rgba?\((\d+),\s?(\d+),\s?(\d+),?\s?([\d\.]+)?\)/);
                return {
                    r:parseInt(m[1]),
                    g:parseInt(m[2]),
                    b:parseInt(m[3]),
                    a:parseFloat(m[4] || 1)
                };
            }
        }
    },
    fn:{
        stop:function()
        {
            var self = this;
            if("frames" in this.self)
            {
                while(this.self.frames.length)
                {
                    clearTimeout(this.self.frames.shift());
                }
            }
            return {
                animate:function(o){return dd.fn.prototype.animate.call(self, o);},
                delay:function(ms){return dd.fn.prototype.delay.call(self, ms);},
                wait:function(){return dd.fn.prototype.wait.call(self);}
            };
        },
        delay:function(ms)
        {
            var self = this;
            return {
                animate:function(o)
                {
                    setTimeout(function(){dd.fn.prototype.animate.call(self, o);}, ms);
                    return {
                        stop:function(o){return dd.fn.prototype.stop.call(self);},
                        delay:function(ms){return dd.fn.prototype.delay.call(self, ms);},
                        wait:function(){return dd.fn.prototype.wait.call(self);}
                    };
                },
                stop:function()
                {
                    setTimeout(function(){return dd.fn.prototype.stop.call(self);}, ms);
                    return {
                        animate:function(o){return dd.fn.prototype.animate.call(self, o);},
                        delay:function(ms){return dd.fn.prototype.delay.call(self, ms);},
                        wait:function(){return dd.fn.prototype.wait.call(self);}
                    };
                },
                wait:function()
                {
                    setTimeout(function(){return dd.fn.prototype.wait.call(self);}, ms);
                    return {
                        animate:function(o){return dd.fn.prototype.animate.call(self, o);},
                        delay:function(ms){return dd.fn.prototype.delay.call(self, ms);},
                        stop:function(o){return dd.fn.prototype.stop.call(self);}
                    };
                }
            }
        },
        wait:function()
        {
            var self = this;
            var mss = this.self.frames.length * 40;
            var r = dd.fn.prototype.delay.call(this, mss);
            r.delay = function(ms)
            {
                setTimeout(function(){return dd.fn.prototype.delay.call(self, ms);}, mss);
                return {
                    animate:function(o)
                    {
                        setTimeout(function(){dd.fn.prototype.animate.call(self, o);}, ms + mss);
                    }
                };
            };
            return r;
        },
        animate:function(o, s)
        {
            s = s || {};
            // Element
            s.self = this.self;
            var e = this.self.e;
            if(!("frames" in this.self))
            {
                this.self.frames = [];
            }
            o.timeStep = o.timeStep || 40;
            o.duration = o.duration || 200;
            if("frames" in o)
            {
                var dur = 0;
                for(var i = 0; i < o.frames.length; i++)
                {
                    dur += o.frames[i].duration || o.timeStep;
                    delete(o.frames[i].duration);
                    this.self.frames.push(setTimeout(function(css, i, m)
                    {
                        dd(s.self).css(css);
                        if(i == m)
                        {
                            if("complete" in o)
                            {
                                o.complete.call(s);
                            }
                        }
                    }, dur, o.frames[i], i, o.frames.length - 1));
                }
            }
            else
            {
                // Minimum duration segement of 40 seconds for 24/FPS
                var steps = Math.ceil(o.duration / o.timeStep);
                var nBackground = "background" in o;
                var nOpacity = "opacity" in o;
                if(nBackground || nOpacity)
                {
                    var c = {};
                    var nc = {};
                    if(nOpacity)
                    {
                        nc.o = o.opacity;
                        c.o = parseFloat(getComputedStyle(e)
                                         .getPropertyValue("opacity"));
                    }
                    if(nBackground)
                    {
                        var b = o.background;
                        // get current color
                        var tc = dd.toRGBA(getComputedStyle(e)
                                          .getPropertyValue("background-color"));
                        c.a = tc.a;
                        c.r = tc.r;
                        c.g = tc.g;
                        c.b = tc.b;
                        nc.a = "a" in b ? b.a : c.a;
                        nc.r = "r" in b ? b.r : c.r;
                        nc.g = "g" in b ? b.g : c.g;
                        nc.b = "b" in b ? b.b : c.b;
                    }
                    var a = {
                        o:(nc.o - c.o) / steps,
                        a:(nc.a - c.a) / steps,
                        r:(nc.r - c.r) / steps,
                        g:(nc.g - c.g) / steps,
                        b:(nc.b - c.b) / steps
                    };
                    // Animate to new
                    for(var i = 0; i < steps; i++)
                    {
                        this.self.frames.push(setTimeout(function(i, m, s)
                        {
                            if(nOpacity)
                            {
                                s.self.e.style.opacity = i == m ? nc.o : Math.round((c.o + (i * a.o)) * 100) / 100;
                            }
                            if(nBackground)
                            {
                                var n = {
                                    a:i == m ? nc.a : Math.round((c.a + (i * a.a)) * 100) / 100,
                                    r:i == m ? nc.r : Math.round(c.r + (i * a.r)),
                                    g:i == m ? nc.g : Math.round(c.g + (i * a.g)),
                                    b:i == m ? nc.b : Math.round(c.b + (i * a.b))
                                };
                                s.self.e.style.backgroundColor = "rgba(" + n.r + ", " + n.g + ", " + n.b + ", " + n.a + ")";
                            }
                            s.self.frames.shift();
                            if(i == m)
                            {
                                if("complete" in o)
                                {
                                    o.complete.call(s);
                                }
                            }
                        }, o.timeStep * i, i, steps - 1, s));
                    }
                };
            }
            var self = this;
            return {
                animate:function(o){return dd.fn.prototype.animate.call(self, o);},
                stop:function(){return dd.fn.prototype.stop.call(self);},
                delay:function(ms){return dd.fn.prototype.delay.call(self, ms);},
                wait:function(){return dd.fn.prototype.wait.call(self);}
            };
        }
    }
});